
#include <stdlib.h>
#include <string.h>
#include "doubly-linked-list.h"


int InitList(DubList *List){
    List->list_head = NULL;
    List->list_length = 0;
    return(0);
}


int ListEmpty(DubList List){
    if (List.list_head == NULL && List.list_length == 0){
        return(1);
    } else if (List.list_head == NULL || List.list_length == 0){
        return(-1);
    } else{
        return(0);
    }
}


int ClearList(DubList *List){
    DubLiNode *p_current = List->list_head;
    while (p_current->next_node){
        p_current = p_current->next_node;
        free(p_current->prior_node);
        --List->list_length;
    }
    free(p_current);
    --List->list_length;
    List->list_head = NULL;
    return((int)List->list_length);
}


int GetElem(DubList List,unsigned int i,ElemType *e){
    if (i == 0 || i > List.list_length) {
        return (-1);
    } else{
        DubLiNode *p_current = List.list_head;
        for (int j = 1; j < i; ++j) {
            p_current = p_current->next_node;
        }
        memcpy(e,&p_current->node_data, sizeof(ElemType));
        return(0);
    }
}

int LocateElem(DubList List,ElemType e){
    if (List.list_head == NULL || List.list_length == 0){
        return(-1);
    }else{
        int location = 1;
        DubLiNode *p_current = List.list_head;
        while (p_current){
            if (memcmp(&p_current->node_data,&e, sizeof(ElemType)) == 0){
                return location;
            }
            p_current = p_current->next_node;
            ++location;
        }
        return(0);
    }
}

int ListInsert(DubList *List,unsigned int i,ElemType e){
    DubLiNode *p_current = List->list_head;
    if(i == 0){
        return(-1);
    } else if (i == 1){
        List->list_head = malloc(sizeof(DubLiNode));
        memset(&List->list_head->node_data,0, sizeof(ElemType));
        List->list_head->prior_node = NULL;
        List->list_head->next_node = p_current;
        ++List->list_length;
        if (p_current != NULL){
            p_current->prior_node = List->list_head;
        }
        return(0);
    }else{
        for (int j = 2; j < i; ++j) {
            if (p_current->next_node == NULL){
                p_current->next_node = malloc(sizeof(ElemType));
                memset(&p_current->next_node->node_data,0, sizeof(ElemType));
                p_current->next_node->next_node = NULL;
                p_current->next_node->prior_node = p_current;
                ++List->list_length;
            }
            p_current = p_current->next_node;
        }
        DubLiNode *tmp = malloc(sizeof(ElemType));
        memcpy(&tmp->node_data,&e, sizeof(ElemType));
        tmp->next_node = p_current->next_node;
        tmp->prior_node = p_current;
        if (p_current->next_node != NULL){
            p_current->next_node->prior_node = tmp;
        }
        p_current->next_node = tmp;
        ++List->list_length;
        return(0);
    }


}
int ListDelete(DubList *List,unsigned int i,ElemType *e){
    if (i == 0 || i > List->list_length){
        return(-1);
    }else if(List->list_length == 1){
        memcpy(e,&List->list_head->node_data, sizeof(ElemType));
        free(List->list_head);
        List->list_head = NULL;
        List->list_length = 0;
        return(0);
    } else if (i == 1){
        List->list_head = List->list_head->next_node;
        memcpy(e,&List->list_head->node_data, sizeof(ElemType));
        free(List->list_head->prior_node);
        List->list_head->prior_node = NULL;
        --List->list_length;
        return(0);
    } else{
        DubLiNode *p_current = List->list_head;
        for (int j = 1; j < i; ++j) {
            p_current = p_current->next_node;
        }
        p_current->prior_node->next_node = p_current->next_node;
        p_current->next_node->prior_node = p_current->prior_node;
        memcpy(e,&p_current->node_data, sizeof(ElemType));
        free(p_current);
        --List->list_length;
        return(0);
    }
}
